package jee.boot.encrypt.dbIntercept;

import jee.boot.encrypt.config.DataEncryptConfig;
import jee.boot.encrypt.config.IEncryptDecrypt;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Properties;

/**
 * 拦截Mybatis的请求参数,如果存在需要被加密的类,字段,则进行加密处理
 */
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),
})
@Component
public class ParameterInterceptor implements Interceptor {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private IEncryptDecrypt encryptDecrypt;
    @Autowired
    private DataEncryptConfig dataEncryptConfig;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (dataEncryptConfig.getEnableEncryptedStorage()) {
            if (invocation.getTarget() instanceof ParameterHandler) {
                ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
                PreparedStatement ps = (PreparedStatement) invocation.getArgs()[0];
                // 反射获取 参数对像
                Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");
                parameterField.setAccessible(true);
                Object parameterObject = parameterField.get(parameterHandler);
                if (parameterObject instanceof ArrayList) {
                    ArrayList resultList = (ArrayList) parameterObject;
                    if (CollectionUtils.isNotEmpty(resultList) && encryptDecrypt.needToDecrypt(resultList.get(0))) {
                        logger.debug("存储-拦截存储数据进行加密处理");
                        for (Object o : resultList) {
                            encryptDecrypt.encrypt(o);
                        }
                    }
                } else {
                    if (encryptDecrypt.needToDecrypt(parameterObject)) {
                        logger.debug("存储-拦截存储数据进行加密处理");
                        encryptDecrypt.encrypt(parameterObject);
                    }
                }
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
